package com.cocotea.valid.handler;

import com.cocotea.valid.constant.MessageConstant;
import com.cocotea.valid.config.ValidConfig;
import com.cocotea.valid.factory.ValidHandlerFactory;
import com.cocotea.valid.service.IValidDispatcher;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

public class ValidHandler {
    public static String dispatch(Field field, Object instance, Class<?> cl) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException, InstantiationException {
        Annotation[] declaredAnnotations = field.getDeclaredAnnotations();
        // 属性值和注解名称映射
        Map<String, String> valueAnnotationMap = new HashMap<>();
        for (Annotation annotation : declaredAnnotations) {
            String annotationName = annotation.annotationType().getSimpleName();
            valueAnnotationMap.put(field.getName(), annotationName);
        }
        for (Map.Entry<String, String> map : valueAnnotationMap.entrySet()) {
            // 2.如果这个注解存在就获取注解的值去进行逻辑
            Object propValue = getMethodeValue(cl, map.getKey(), instance);
            IValidDispatcher dispatcher = ValidHandlerFactory.getInstance(ValidConfig.DEFAULT);
            // 分发到对应的校验处理器
            String s = dispatcher.doValid(field, propValue, map.getValue());
            // 自定义校验
            if (MessageConstant.SUCCESS.equals(s) && !"".equals(ValidConfig.VALID_HANDLER_CLASS)) {
                dispatcher = ValidHandlerFactory.getInstance(ValidConfig.VALID_HANDLER_CLASS);
                s = dispatcher
                        .getClass()
                        .getMethod("doValid", Field.class, Object.class, String.class)
                        .invoke(dispatcher, field, propValue, map.getValue()).toString();
            }
            return s;
        }
        return MessageConstant.SUCCESS;
    }

    /**
     * 获取属性值
     * @return 属性值
     */
    private static Object getMethodeValue(Class<?> cl, String prop, Object instance) throws InvocationTargetException, IllegalAccessException {
        for (Method method : cl.getMethods()) {
            // 过滤非getter方法
            if (!method.getName().startsWith("get")) continue;
            // 参数属性名称
            String propName = method.getName().substring(4);
            String prefix = method.getName().substring(3, 4).toLowerCase(Locale.ROOT);
            if (prop.equals(prefix + propName)) {
                return method.invoke(instance);
            }
        }
        return null;
    }
}
